package libReactionCore;


import org.omg.CORBA.StringHolder;

import com.rois.librois.RoIS.Argument;
import com.rois.librois.RoIS.Completed_Status;
import com.rois.librois.RoIS.ErrorType;
import com.rois.librois.RoIS.Parameter;
import com.rois.librois.RoIS.ParameterListHolder;
import com.rois.librois.RoIS.Result;
import com.rois.librois.RoIS.ResultListHolder;
import com.rois.librois.RoIS.ReturnCode_t;
import com.rois.librois.libRoISComp.ComponentEntity;
import com.rois.librois.libRoISComp.LocalParameter;
import com.rois.librois.libRoISComp.MessageParameter;
import com.rois.librois.libRoISComp.libRoISComp;


public class ComponentEntityImpl implements ComponentEntity{
	/**
	 * libRoIS object
	 */
	private libRoISComp libRoIS;

	/**
	 * counter for binding
	 */
	int bind_count;

	/**
	 * Execute Operation class for Reaction
	 */
	private ExecuteOperation exec;

	/**
	 * list of component parameters
	 */
	LocalParameter[] comp_params = null;

	/**
	 * list of query parameters
	 */
	MessageParameter[] qry_params = null;

	/**
	 * list of event parameters
	 */
	MessageParameter[] evt_params = null;

	/**
	 * create component entity
	 * @param lib_obj libRoIS object
	 * @param exec_obj ExecuteOperation object
	 */
	public ComponentEntityImpl(
		libRoISComp lib_obj,
		ExecuteOperation exec_obj
	)
	{
		libRoIS = lib_obj;
		exec = exec_obj;
		bind_count = 0;

		////////////////////////////////////////////////
		// create parameters based on Profile
		////////////////////////////////////////////////
		// component parameter
		comp_params = new LocalParameter[2];
		comp_params[0] = new LocalParameter(
			"available_reactions",
			"set_RoIS_Identifier",
			"18",
			"/codebook/reaction_codebook.csv"	//@@ codebook for RoIS_Identifier
		);
		comp_params[1] = new LocalParameter(
			"reaction_ref",
			"RoIS_Identifier",
			"default",
			"/codebook/reaction_codebook.csv"	//@@ codebook for RoIS_Identifier
		);

		//query result
		qry_params = new MessageParameter[2];
		// ### Parameter for "get_parameter" ###
		//@@ need to sync with component_parameters
		qry_params[0] = new MessageParameter("get_parameter");
		LocalParameter[]_qry_params1 = new LocalParameter[2];
		_qry_params1[0] = new LocalParameter(
			"available_reactions",
			"set_RoIS_Identifier",
			"18",
			"/codebook/reaction_codebook.csv"	//@@ codebook for RoIS_Identifier
		);
		_qry_params1[1] = new LocalParameter(
			"reaction_ref",
			"RoIS_Identifier",
			"default",
			"/codebook/reaction_codebook.csv"	//@@ codebook for RoIS_Identifier
		);
		qry_params[0].addParam(_qry_params1);

		// ### Parameter for "component_status" ###
		qry_params[1] = new MessageParameter("component_status");
		LocalParameter[]_qry_params2 = new LocalParameter[1];
		_qry_params2[0] = new LocalParameter(
			"status",
			"Component_Status",
			""
		);
		qry_params[1].addParam(_qry_params2);
	}

	@Override
	public ReturnCode_t bind()
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_OK;

		System.out.println("accepted [bind]");
		bind_count++;

		return roRes;
	}

	@Override
	public ReturnCode_t release()
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_OK;

		System.out.println("accepted [release]");
		bind_count--;

		return roRes;
	}

	@Override
	public ReturnCode_t get_parameter(
		ParameterListHolder parameters
	)
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_BAD_PARAMETER;

		System.out.println("accepted [get_parameter]");

		// Return specified parameters when there are specified parameters
		if(parameters.value.length!=0)
		{
			int size = parameters.value.length;
			for(int i=0; i<size; i++)
			{
				for(int j=0; j<comp_params.length; j++)
				{
					if(parameters.value[i].name.matches(comp_params[j].name)
					&& parameters.value[i].data_type_ref.matches(comp_params[j].data_type_ref))
					{
						org.omg.CORBA.Any any_tmp = org.omg.CORBA.ORB.init().create_any();
						any_tmp.insert_string(comp_params[j].getParam());
						parameters.value[i].value = any_tmp;
						roRes = ReturnCode_t.RoIS_OK;
					}
				}
			}
		}
		// Return all parameters when there is no specified parameter
		else
		{
			Parameter[] _parameters = new Parameter[comp_params.length];
			for(int i=0; i<comp_params.length; i++)
			{
				_parameters[i] = new Parameter();
				_parameters[i].name = comp_params[i].name;
				_parameters[i].data_type_ref = comp_params[i].data_type_ref;
				org.omg.CORBA.Any any_tmp = org.omg.CORBA.ORB.init().create_any();
				any_tmp.insert_string(comp_params[i].getParam());
				_parameters[i].value = any_tmp;
			}
			parameters.value = _parameters;
			roRes = ReturnCode_t.RoIS_OK;
		}

		return roRes;
	}

	@Override
	public ReturnCode_t set_parameter(
		Parameter[] parameters,
		StringHolder command_id
	)
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_BAD_PARAMETER;

		System.out.println("accepted [set_parameter]");

		// set specified parameters when there are specified parameters
		if(parameters.length!=0)
		{
			for(int i=0; i<parameters.length; i++)
			{
				for(int j=0; j<comp_params.length; j++)
				{
					if(parameters[i].name.matches(comp_params[j].name)
					&& parameters[i].data_type_ref.matches(comp_params[j].data_type_ref))
					{
						comp_params[j].setParam(parameters[i].value.extract_string());
						qry_params[0].parameters[j].setParam(parameters[i].value.extract_string());		//@@
						exec.set_parameter(command_id.value);	// only for completed message
						roRes = ReturnCode_t.RoIS_OK;
					}
				}
			}
		}
		return roRes;
	}

	@Override
	public ReturnCode_t execute(
		String command_type,
		Argument[] arguments,
		StringHolder command_id
	)
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_OK;

		System.out.println("accepted [execute]");
		System.out.println(">>>command_type:"+ command_type);
		System.out.println(">>>command_id:"+ command_id.value);
		if(command_type.matches("start"))
		{
			roRes = exec.start(comp_params[1].getParam(), command_id.value);
		}
		else if(command_type.matches("stop"))
		{
			roRes = exec.stop(command_id.value);
		}
		else if(command_type.matches("suspend"))
		{
			roRes = exec.suspend(command_id.value);
		}
		else if(command_type.matches("resume"))
		{
			roRes = exec.resume(command_id.value);
		}
		else if(command_type.matches("set_parameter"))
		{
			Parameter[] parameters;
			parameters = new Parameter[arguments.length];
			for(int i=0; i<arguments.length; i++)
			{
				parameters[i] = new Parameter();
				parameters[i].name = arguments[i].name;
				parameters[i].data_type_ref = arguments[i].data_type_ref;
				parameters[i].value = arguments[i].value;
			}
			roRes = this.set_parameter(parameters, command_id);
		}
		else
		{
			roRes = ReturnCode_t.RoIS_BAD_PARAMETER;
		}

		return roRes;
	}

	@Override
	public ReturnCode_t query(
		String query_type,
		String condition,
		ResultListHolder results
	)
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_BAD_PARAMETER;

		System.out.println("accepted [query]");
		System.out.println(">>>query_type:"+ query_type);
		System.out.println(">>>condition:"+ condition);

		for(int i=0; i<qry_params.length; i++)
		{
			if(query_type.matches(qry_params[i].message_type))
			{
				// Return specified parameters when there are specified parameters
				if(results.value.length!=0)
				{
					int size = results.value.length;
					for(int j=0; j<size; j++)
					{
						for(int k=0; k<qry_params[i].parameters.length; k++)
						{
							if(results.value[j].name.matches(qry_params[i].parameters[k].name)
							&& results.value[j].data_type_ref.matches(qry_params[i].parameters[k].data_type_ref))
							{
								org.omg.CORBA.Any any_tmp = org.omg.CORBA.ORB.init().create_any();
								any_tmp.insert_string(qry_params[i].parameters[k].getParam());
								results.value[j].value = any_tmp;
								roRes = ReturnCode_t.RoIS_OK;
							}
						}
					}
				}
				// Return all parameters when there is no specified parameter
				else
				{
					Result[] _results = new Result[qry_params[i].parameters.length];
					for(int j=0; j<qry_params[i].parameters.length; j++)
					{
						_results[j] = new Result();
						_results[j].name = qry_params[i].parameters[j].name;
						_results[j].data_type_ref = qry_params[i].parameters[j].data_type_ref;
						org.omg.CORBA.Any any_tmp = org.omg.CORBA.ORB.init().create_any();
						any_tmp.insert_string(qry_params[i].parameters[j].getParam());
						_results[j].value = any_tmp;
					}
					results.value = _results;
					roRes = ReturnCode_t.RoIS_OK;
				}
			}
		}
		return roRes;
	}

	@Override
	public ReturnCode_t subscribe(
		String event_type,
		String condition,
		StringHolder subscribe_id
	)
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_OK;

		System.out.println("accepted [subscribe]");
		System.out.println(">>>event_type:"+ event_type);
		System.out.println(">>>condition:"+ condition);
		System.out.println(">>>subscribe_id:"+ subscribe_id.value);

		return roRes;
	}

	@Override
	public ReturnCode_t unsubscribe(
		String subscribe_id
	)
	{
		ReturnCode_t roRes = ReturnCode_t.RoIS_OK;

		System.out.println("accepted [unsubscribe]");
		System.out.println(">>>subscribe_id:"+ subscribe_id);

		return roRes;
	}

	@Override
	public void completed(
		String commandId,
		Completed_Status status,
		ResultListHolder results)
	{
		libRoIS.completed(commandId, status, results);
	}

	@Override
	public void receive_error(
		ErrorType errorType,
		ResultListHolder results
	)
	{
 		libRoIS.receive_error(errorType, results);
	}

	@Override
	public void receive_event(
		String eventType,
		String subscribeId,
		ResultListHolder results
	)
	{
  		libRoIS.receive_event(eventType, subscribeId, results);
	}

	@Override
	public int get_event_prameter_size()
	{
		int iRes = evt_params.length;
		return iRes;
	}

	@Override
	public void get_event_parameters(
		MessageParameter[] parameters
	)
	{
			parameters = evt_params;
	}

	@Override
	public int get_query_prameter_size()
	{
		int iRes = qry_params.length;
		return iRes;
	}

	@Override
	public void get_query_parameters(
		MessageParameter[] parameters
	)
	{
		parameters = qry_params;
	}

}
